package com.wsoft.bpm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.wsoft.bpm.service.RunProcessService;
import com.wsoft.bpm.vo.TaskTodoVO;
import com.wsoft.core.cmd.DcConfigService;
import org.activiti.engine.task.Task;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 提供给外部的待办接口
 *
 * @Author zhonglj
 * @Date 2025/1/13 10:41
 */
@Service("bpmTodoService")
public class BpmTodoService implements DcConfigService {
    // 使用可继承的ThreadLocal保证异步调用安全（修改）
    private static final ThreadLocal<Map<String, Object>> LAST_PARAMS = new InheritableThreadLocal<>();
    private static final ThreadLocal<List<TaskTodoVO>> CACHED_RESULT = new InheritableThreadLocal<>();
    @Resource
    private RunProcessService runProcessService;

    @Override
    public Long count(Map<String, Object> paramMap) {
        List<TaskTodoVO> result = getCachedOrFresh(paramMap);
        return (long) result.size();
    }

    @Override
    public List<TaskTodoVO> list(Map<String, Object> paramMap) {
        List<TaskTodoVO> result = getCachedOrFresh(paramMap);
        clearCache();
        return result;
    }

    @NotNull
    private List<TaskTodoVO> getTaskTodoVOS(Map<String, Object> paramMap) {
        String title = MapUtil.getStr(paramMap, "title");
        LocalDateTime start = null;
        LocalDateTime end = null;
        Object createTimeObj = paramMap.get("createTime");
        if (createTimeObj != null && createTimeObj instanceof List) {
            List<String> createTimes = (List<String>) createTimeObj;
            if (CollUtil.isNotEmpty(createTimes)) {
                start = DateUtil.parseLocalDateTime(createTimes.get(0));
                end = DateUtil.parseLocalDateTime(createTimes.get(1));
            }
        }

        final LocalDateTime startTime = start;
        final LocalDateTime endTime = end;
        List<Task> tasks = runProcessService.todoList();
        List<TaskTodoVO> collect = runProcessService.packageExtraTodoData(tasks);
        collect = collect.stream()
                .filter(vo -> {
                    if (StrUtil.isNotBlank(title)) {
                        if (!StrUtil.contains(vo.getTitle(), title)) {
                            return false;
                        }
                    }
                    if (startTime != null) {
                        if (!(startTime.compareTo(vo.getCreateTime()) <= 0)) {
                            return false;
                        }
                    }

                    if (endTime != null) {
                        LocalDateTime offset = LocalDateTimeUtil.offset(endTime, 1, ChronoUnit.DAYS);
                        if (!(offset.compareTo(vo.getCreateTime()) > 0)) {
                            return false;
                        }
                    }

                    return true;
                }).collect(Collectors.toList());
        return collect;
    }

    private List<TaskTodoVO> getCachedOrFresh(Map<String, Object> paramMap) {
        // 参数相同且存在缓存时直接返回（新增）
        if (isSameParams(paramMap) && CACHED_RESULT.get() != null) {
            return CACHED_RESULT.get();
        }

        List<TaskTodoVO> freshResult = getTaskTodoVOS(paramMap);
        cacheResult(paramMap, freshResult);
        return freshResult;
    }

    private boolean isSameParams(Map<String, Object> newParams) {
        Map<String, Object> lastParams = LAST_PARAMS.get();
        return lastParams != null && lastParams.equals(newParams);
    }

    private void cacheResult(Map<String, Object> params, List<TaskTodoVO> result) {
        LAST_PARAMS.set(new HashMap<>(params));
        CACHED_RESULT.set(result);
    }

    private void clearCache() {
        LAST_PARAMS.remove();
        CACHED_RESULT.remove();
    }
}
